import { createTaskQueue, arrified, createStateNode, getTag } from "../Misc"

// 任务队列
const taskQueue = createTaskQueue()

// 存储子任务
let subTask = null

let pendingCommit = null

const commitAllWork = fiber => {
    fiber.effects.forEach(item => {
        if(item.effectTag === 'placement') {
            item.parent.stateNode.appendChild(item.stateNode)
        }
    })
}

const getFirstTask = () => {
    // 从任务队列中获取任务
    const task = taskQueue.pop()
    // 返回最外层节点的fiber对象
    return {
        props: task.props,
        stateNode: task.dom,
        tag: "host_root",
        effects: [],
        child: null
    }
}

const reconcileChildren = (fiber, children) => {
    // children 可能是对象（render里的根节点），可能是数组（createElement创建的节点）
    // 将children转换成数组
    const arrifiedChildren = arrified(children)

    let index = 0
    let numberOfElements = arrifiedChildren.length
    let element = null
    let newFiber = null
    let prevFiber = null

    while(index < numberOfElements) {
        element = arrifiedChildren[index]
        console.log(element)
        // 构建子级 fiber对象
        newFiber = {
            type: element.type,
            props: element.props,
            tag: getTag(element),
            effects: [],
            effectTag: "placement",
            parent: fiber
        }

        // 为 fiber 节点添加DOM对象或者组件实例对象
        newFiber.stateNode = createStateNode(newFiber)

        if(index === 0) {
            // 为父级fiber添加子级fiber
            fiber.child = newFiber
        } else {
            // 为fiber添加兄弟fiber
            prevFiber.sibling = newFiber
        }
        // 记录新创建的fiber
        prevFiber = newFiber
        index++
    }
}

// 执行任务 返回新的任务
const executeTask = fiber => {
    reconcileChildren(fiber, fiber.props.children)

    if(fiber.child) {
        return fiber.child
    }

    // 如果存在同级 返回同级 构建同级的子级
    // 如果同级不存在 返回到父级 看父级是否有同级
    let currentExecuteFiber = fiber

    while(currentExecuteFiber.parent) {
        currentExecuteFiber.parent.effects = currentExecuteFiber.parent.effects.concat(currentExecuteFiber.effects.concat([currentExecuteFiber]))

        if(currentExecuteFiber.sibling) {
            return currentExecuteFiber.sibling
        }
        currentExecuteFiber = currentExecuteFiber.parent
    }

    pendingCommit = currentExecuteFiber

    console.log(currentExecuteFiber)
}


const workLoop = (deadline) => {
    // 子任务不存在，则获取子任务
    if(!subTask) {
        subTask = getFirstTask()
    }

    // 循环执行任务
    // 当任务存在且浏览器有空闲时间则执行任务
    // 执行任务后需要返回新的任务
    while(subTask && deadline.timeRemaining() > 1) {
        subTask = executeTask(subTask)
    }

    // 第二阶段
    if(pendingCommit) {
        commitAllWork(pendingCommit)
    }
}

const performTask = deadline => {
    // 执行任务
    workLoop(deadline)

    // 判断任务是否存在、任务队列中是否有任务
    // 存在则通知浏览器空闲时继续执行任务
    if(subTask || !taskQueue.isEmpty()) {
        requestIdleCallback(performTask)
    }
}
export const render = (element, dom) => {
    // console.log(dom)
    // console.log(element)

    /*
    ** 1. 向任务队列添加任务【通过vdom对象构建fiber对象】
    ** 2. 指定在浏览器空闲时执行任务
    */

    // 1. 向任务队列添加根任务
    taskQueue.push({
        dom,
        props: { children: element },
    })

    // console.log(taskQueue.pop())

    // 2. 浏览器空闲时执行任务
    requestIdleCallback(performTask)
}